﻿using Kenly.DBFramework.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data;
using System;
using Kenly.DBFramework.Gateway;
using System.Collections.Generic;
using System.Collections;

using Kenly.UTAssist;
using Kenly.DBFramework.TestModel.HumanResources;

namespace Kenly.DBFramework.Tests
{


    /// <summary>
    ///这是 EntityMapperTest 的测试类，旨在
    ///包含所有 EntityMapperTest 单元测试
    ///</summary>
    [TestClass()]
    public class EntityMapperTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性
        // 
        //编写测试时，还可使用以下属性:
        //
        //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //使用 TestInitialize 在运行每个测试前先运行代码
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //使用 TestCleanup 在运行完每个测试后运行代码
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        //[TestMethod()]
        //public void InvokeAllWithNullTest()
        //{
        //    var tester = new MethodTester(typeof(EntityMapper));

        //    tester.InvokeAllWithNull();
        //}

        /// <summary>
        ///ToTable 的测试
        ///</summary>
        [TestMethod()]
        public void ToTableAdaptedTest()
        {
            IList entities = EntityMapperHelper.CreateEntities();

            //DataTable table = EntityMapper.ToTable(entities);

            TestCase testcase = new TestCase(typeof(EntityMapper), "ToTable");

            testcase.Execute<DataTable>(p => ValidateAdaptedDataTable(p), entities);

            object[] args = { null };
            testcase.Execute<DataTable>(p => p == null, args);

            testcase.Execute<DataTable>(p => p.Rows.Count == 0, new ArrayList());

            entities = new ArrayList();
            entities.Add(null);
            testcase.Execute<DataTable>(p => p.Rows.Count == 0, entities);
        }

        private static bool ValidateAdaptedDataTable(DataTable table)
        {
            Type entityType = EntityMapperHelper.GetEntityType();

            if (table.TableName != entityType.Name)
            {
                return false;
            }

            if (!table.Columns.Contains("StudentID"))
            {
                return false;
            }

            if (!table.Columns.Contains("NationalIDNumber"))
            {
                return false;
            }

            return true;
        }


        /// <summary>
        ///ToTable 的测试
        ///</summary>
        [TestMethod()]
        public void ToTableTest()
        {
            bool isAdapted = false;
            IList entities = EntityMapperHelper.CreateEntities();

            //DataTable table = EntityMapper.ToTable(entities, isAdapted);

            TestCase testcase = new TestCase(typeof(EntityMapper), "ToTable");

            testcase.Execute<DataTable>(p => ValidateDataTable(p), entities, isAdapted);

            testcase.Execute<DataTable>(p => p == null, null, isAdapted);
            testcase.Execute<DataTable>(p => p.Rows.Count == 0, new ArrayList(), isAdapted);

            entities = new ArrayList();
            entities.Add(null);
            testcase.Execute<DataTable>(p => p.Rows.Count == 0, entities, isAdapted);
        }

        private static bool ValidateDataTable(DataTable table)
        {
            Type entityType = EntityMapperHelper.GetEntityType();

            if (table.TableName != entityType.Name)
            {
                return false;
            }

            if (!table.Columns.Contains(Student.StudentIDColumn))
            {
                return false;
            }

            if (!table.Columns.Contains(Student.NationalIDNumberColumn))
            {
                return false;
            }

            return true;
        }

        /// <summary>
        ///ToPropertyName 的测试
        ///</summary>
        [TestMethod()]
        public void ToPropertyNameTest()
        {
            //string actual = EntityMapper.ToPropertyName(columnName, entityType);

            TestCase testcase = new TestCase(typeof(EntityMapper), "ToPropertyName");
            Type entityType = EntityMapperHelper.GetEntityType();

            testcase.Execute<string>(p => p == "StudentID", Student.StudentIDColumn, entityType);

            testcase.Execute<string>(p => p == null, string.Empty, entityType);
            testcase.Execute<string>(p => p == null, null, entityType);
            testcase.Execute<string>(p => p == null, Student.StudentIDColumn, null);

        }

        /// <summary>
        ///ToColumnName 的测试
        ///</summary>
        [TestMethod()]
        public void ToColumnNameTest()
        {
            //string actual = EntityMapper.ToColumnName(propertyName, entityType);

            string propertyName = "StudentID";

            TestCase testcase = new TestCase(typeof(EntityMapper), "ToColumnName");
            Type entityType = EntityMapperHelper.GetEntityType();

            testcase.Execute<string>(p => p == Student.StudentIDColumn, propertyName, entityType);

            testcase.Execute<string>(p => p == null, string.Empty, entityType);
            testcase.Execute<string>(p => p == null, null, entityType);
            testcase.Execute<string>(p => p == null, propertyName, null);
        }

        /// <summary>
        ///ToEntity 的测试
        ///</summary>
        [TestMethod()]
        public void ToEntityTest()
        {
            //DataRow adaptedRow = null; 
            //Type entityType = null; 
            //object actual = EntityMapper.ToEntity(adaptedRow, entityType);

            TestCase testcase = new TestCase(typeof(EntityMapper), "ToEntity");
            Type entityType = EntityMapperHelper.GetEntityType();
            DataRow adaptedRow = EntityMapperHelper.CreateAdaptedDataRow();

            testcase.Execute<object>(p => p != null, adaptedRow, entityType);
            testcase.Execute<object>(p => p is Student, adaptedRow, entityType);
            testcase.Execute<object>(p => ((Student)p).StudentID == 100, adaptedRow, entityType);

            testcase.Execute<object>(p => p == null, adaptedRow, null);
            testcase.Execute<object>(p => p == null, null, entityType);
            testcase.Execute<object>(p => p == null, null, null);

        }

        /// <summary>
        ///ToEntities 的测试
        ///</summary>
        [TestMethod()]
        public void ToEntitiesFromDataRowsTest()
        {
            //DataRowCollection adaptedRows = null;
            //Type entityType = null;
            //IList actual = EntityMapper.ToEntities(adaptedRows, entityType);

            DataTable table = EntityMapperHelper.CreateAdaptedTable();
            ValidateToEntitiesFromDataRows(table);

        }

        private static void ValidateToEntitiesFromDataRows(DataTable table)
        {
            TestCase testcase = new TestCase(typeof(EntityMapper), "ToEntities");
            Type entityType = EntityMapperHelper.GetEntityType();
            DataRowCollection adaptedRows = table.Rows;

            object[] args = new object[] { adaptedRows, entityType };

            testcase.Execute<IList>(p => p.Count == adaptedRows.Count, args);
            testcase.Execute<IList>(p => p[0] is Student, args);
            testcase.Execute<IList>(p => ((Student)p[0]).StudentID == 100, args);

            adaptedRows = (new DataTable()).Rows;
            testcase.Execute<IList>(p => p.Count == 0, adaptedRows, entityType);

            testcase.Execute<IList>(p => p == null, adaptedRows, null);
            testcase.Execute<IList>(p => p == null, null, entityType);
            testcase.Execute<IList>(p => p == null, null, null);
        }

        /// <summary>
        ///ToEntities 的测试
        ///</summary>
        [TestMethod()]
        public void ToEntitiesTest()
        {
            //DataTable table = null; 
            //Type entityType = null; 
            //IList actual = EntityMapper.ToEntities(table, entityType);

            DataTable table = EntityMapperHelper.CreateAdaptedTable();
            ValidateToEntities(table);
        }

        private static void ValidateToEntities(DataTable table)
        {
            TestCase testcase = new TestCase(typeof(EntityMapper), "ToEntities");
            Type entityType = EntityMapperHelper.GetEntityType();

            testcase.Execute<IList>(p => p.Count == table.Rows.Count, table, entityType);
            testcase.Execute<IList>(p => p[0] is Student, table, entityType);
            testcase.Execute<IList>(p => ((Student)p[0]).StudentID == 100, table, entityType);

            testcase.Execute<IList>(p => p.Count == 0, new DataTable(), entityType);

            testcase.Execute<IList>(p => p == null, table, null);
            testcase.Execute<IList>(p => p == null, null, entityType);
            testcase.Execute<IList>(p => p == null, null, null);
        }

        /// <summary>
        ///CreateTable 的测试
        ///</summary>
        [TestMethod()]
        public void CreateAdaptedTableTest()
        {
            //Type entityType = null; 
            //DataTable actual = EntityMapper.CreateTable(entityType);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CreateTable");
            Type entityType = EntityMapperHelper.GetEntityType();

            //testcase.Execute<DataTable>(p => p.TableName == entityType.Name, entityType);
            testcase.Execute<DataTable>(p => IsFullAdapted(p), entityType);

            object[] args = new object[] { null };
            testcase.Execute<DataTable>(p => p == null, args);
        }

        /// <summary>
        ///CreateTable 的测试
        ///</summary>
        [TestMethod()]
        public void CreateTableTest()
        {
            bool isAdapted = false;
            //DataTable actual = EntityMapper.CreateTable(entityType,isAdapted);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CreateTable");
            Type entityType = EntityMapperHelper.GetEntityType();

            testcase.Execute<DataTable>(p => IsAdaptedFullToDatabase(p), entityType, isAdapted);

            testcase.Execute<DataTable>(p => p == null, null, isAdapted);
        }

        /// <summary>
        ///CreateEntities 的测试
        ///</summary>
        [TestMethod()]
        public void CreateEntitiesTest()
        {
            //IList actual = EntityMapper.CreateEntities(entityType, count);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CreateEntities");
            Type entityType = EntityMapperHelper.GetEntityType();
            int count = 2;

            testcase.Execute<IList>(p => p.Count == count, entityType, count);
            testcase.Execute<IList>(p => IsMatchedType(p, entityType), entityType, count);

            testcase.Execute<IList>(p => p.Count == 0, entityType, 0);
            testcase.Execute<IList>(p => p.Count == 0, entityType, -1);
            testcase.Execute<IList>(p => p == null, null, count);
        }

        private static bool IsMatchedType(IList entities, Type expectedType)
        {
            foreach (var item in entities)
            {
                if (item.GetType() != expectedType)
                {
                    return false;
                }
            }

            return true;
        }


        /// <summary>
        ///CanCopyToEntity 的测试
        ///</summary>
        [TestMethod()]
        public void CanCopyToEntityTest()
        {
            object entity = new Student();
            DataRow row = EntityMapperHelper.CreateAdaptedDataRow();

            //EntityMapper.CanCopyToEntity(entity, row);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CanCopyToEntity");

            testcase.Execute<bool>(p => p == true, entity, row);

            testcase.Execute<bool>(p => p == false, null, row);
            testcase.Execute<bool>(p => p == false, entity, null);
            testcase.Execute<bool>(p => p == false, new object(), row);
            testcase.Execute<bool>(p => p == false, null, null);
        }


        /// <summary>
        ///CopyToEntity 的测试
        ///</summary>
        [TestMethod()]
        public void CopyToEntityTest()
        {
            object entity = EntityMapperHelper.CreateEmptyEntity();
            DataRow row = EntityMapperHelper.CreateAdaptedDataRow();

            //EntityMapper.CopyToEntity(entity, row);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CopyToEntity");

            testcase.Execute(entity, row);
            testcase.AssertResult<object>(p => (p is Student), entity);
            testcase.AssertResult<object>(p => ((Student)p).StudentID == 100, entity);

            testcase.Execute(entity, null);
            testcase.Execute(null, row);
            testcase.Execute(null, null);
        }

        /// <summary>
        ///CopyToEntities 的测试
        ///</summary>
        [TestMethod()]
        public void CopyToEntitiesTest()
        {
            IList entities = EntityMapperHelper.CreateEmptyEntities();

            DataTable adaptedTable = EntityMapperHelper.CreateAdaptedTable();
            //EntityMapper.CopyToEntities(entities, adaptedTable);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CopyToEntities");

            testcase.Execute(entities, adaptedTable);
            testcase.AssertResult<IList>(p => p.Count == entities.Count, entities);
            testcase.AssertResult<IList>(p => ((Student)p[0]).StudentID == 100 && ((Student)p[1]).StudentID == 101, entities);

            testcase.Execute(null, adaptedTable);
            testcase.Execute(entities, null);
            testcase.Execute(null, null);
        }

        /// <summary>
        ///CopyToEntities 的测试
        ///</summary>
        [TestMethod()]
        public void CopyToEntitiesFromAdaptedRowsTest()
        {
            IList entities = EntityMapperHelper.CreateEmptyEntities();
            DataRowCollection adaptedRows = EntityMapperHelper.CreateAdaptedTable().Rows;
            //EntityMapper.CopyToEntities(entities, adaptedRows);

            TestCase testcase = new TestCase(typeof(EntityMapper), "CopyToEntities");

            testcase.Execute(entities, adaptedRows);
            testcase.AssertResult<IList>(p => p.Count == entities.Count, entities);
            testcase.AssertResult<IList>(p => ((Student)p[0]).StudentID == 100 && ((Student)p[1]).StudentID == 101, entities);

            testcase.Execute(entities, null);
            testcase.Execute(null, adaptedRows);
            testcase.Execute(null, null);
        }

        /// <summary>
        ///AdaptToEntity 的测试
        ///</summary>
        [TestMethod()]
        public void AdaptToEntityByColumnAttributesTest()
        {
            DataTable rawTable = EntityMapperHelper.CreateRawTable();
            List<ColumnAttribute> columnAttributes = EntityMapperHelper.CreateColumnAttributes();

            //EntityMapper.AdaptToEntity(rawTable, columnAttributes);

            TestCase testcase = new TestCase(typeof(EntityMapper), "AdaptToEntity");

            testcase.Execute(rawTable, columnAttributes);
            testcase.AssertResult<DataTable>(p => IsPartialAdapted(p), rawTable);

            testcase.Execute(rawTable, null);
            testcase.Execute(null, columnAttributes);
            testcase.Execute(null, null);
        }

        private static bool IsFullAdapted(DataTable table)
        {
            return table.TableName == "Student" &&
                table.Columns.Contains("StudentID") &&
                table.Columns.Contains("NationalIDNumber");
        }

        private static bool IsPartialAdapted(DataTable table)
        {
            return table.TableName == Student.TableName &&
                table.Columns.Contains("StudentID") &&
                table.Columns.Contains("NationalIDNumber");
        }

        /// <summary>
        ///AdaptToEntity 的测试
        ///</summary>
        [TestMethod()]
        public void AdaptToEntityTest()
        {
            DataTable rawTable = EntityMapperHelper.CreateRawTable();
            Type entityType = EntityMapperHelper.GetEntityType();
            //EntityMapper.AdaptToEntity(rawTable, entityType);

            TestCase testcase = new TestCase(typeof(EntityMapper), "AdaptToEntity");

            testcase.Execute(rawTable, entityType);
            testcase.AssertResult<DataTable>(p => IsFullAdapted(p), rawTable);

            testcase.Execute(rawTable, null);
            testcase.Execute(null, entityType);
            testcase.Execute(null, null);
        }

        /// <summary>
        ///AdaptToDatabase 的测试
        ///</summary>
        [TestMethod()]
        public void AdaptToDatabaseByColumnAttributesTest()
        {
            DataTable adaptedTable = EntityMapperHelper.CreateAdaptedTable();
            List<ColumnAttribute> columnAttributes = EntityMapperHelper.CreateColumnAttributes();
            //EntityMapper.AdaptToDatabase(adaptedTable, columnAttributes);

            TestCase testcase = new TestCase(typeof(EntityMapper), "AdaptToDatabase");

            testcase.Execute(adaptedTable, columnAttributes);
            testcase.AssertResult<DataTable>(p => IsAdaptedPartialToDatabase(p), adaptedTable);

            testcase.Execute(adaptedTable, null);
            testcase.Execute(null, columnAttributes);
            testcase.Execute(null, null);
        }

        private static bool IsAdaptedPartialToDatabase(DataTable table)
        {
            return table.Columns.Contains(Student.StudentIDColumn) &&
                table.Columns.Contains(Student.NationalIDNumberColumn);
        }

        /// <summary>
        ///AdaptToDatabase 的测试
        ///</summary>
        [TestMethod()]
        public void AdaptToDatabaseTest()
        {
            DataTable adaptedTable = EntityMapperHelper.CreateAdaptedTable();
            Type entityType = EntityMapperHelper.GetEntityType();
            //EntityMapper.AdaptToDatabase(adaptedTable, entityType);

            TestCase testcase = new TestCase(typeof(EntityMapper), "AdaptToDatabase");

            testcase.Execute(adaptedTable, entityType);
            testcase.AssertResult<DataTable>(p => IsAdaptedFullToDatabase(p), adaptedTable);

            testcase.Execute(adaptedTable, null);
            testcase.Execute(null, entityType);
            testcase.Execute(null, null);
        }

        private static bool IsAdaptedFullToDatabase(DataTable table)
        {
            return table.TableName == Student.TableName &&
                table.Columns.Contains(Student.StudentIDColumn) &&
                table.Columns.Contains(Student.NationalIDNumberColumn);
        }


    }
}
